package com.unionpay.db;

import java.io.Reader;
import java.io.StringReader;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.log4j.Logger;

/**
 * 加载jdbc配置，生成mybaties.xml，获得Mapper集合
 * 
 * @author liuzy
 * @since 2016年5月1日
 */
public class Mybaties {
	private static Logger logger = Logger.getLogger(Mybaties.class);
	private static SqlSessionFactory sqlSessionFactory;
	private static ConcurrentHashMap<Class<?>, Object> mappers = new ConcurrentHashMap<Class<?>, Object>();

	public static void init(Properties p) {
		try {

			MybatiesConfig config = new MybatiesConfig(p);
			// 生成默认连接池配置
//			String xml = config.buildXml();
			// 生成druid连接池配置
			String xml = config.buildXml(MyDruidDataSourceFactory.class.getName());
			logger.debug(xml);

			Reader reader = new StringReader(xml);
			sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
			reader.close();

			for (final Class<?> mapperClass : config.getMappers()) {
				Object proxy = Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), 
						new Class[] { mapperClass }, 
						new InvocationHandler() {
							@Override
							public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
								Object result = null;
								SqlSession session = openSession();
								Object mapper = session.getMapper(mapperClass);
								result = method.invoke(mapper, args);
								session.close();
								return result;
							}
						});
				mappers.put(mapperClass, proxy);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@SuppressWarnings("unchecked")
	public static <T> T getMapper(Class<T> mapper) {
		return (T) mappers.get(mapper);
	}

	public static SqlSession openSession() {
		return sqlSessionFactory.openSession(true);
	}

}
